ยกระดับคุณภาพโค้ด JavaScript ของคุณด้วย pre-commit hooks เรียนรู้วิธีตั้งค่าและใช้ประตูคุณภาพโค้ดเพื่อโปรเจกต์ที่สะอาดและดูแลรักษาง่ายขึ้น
ประตูคุณภาพโค้ด JavaScript: การตั้งค่า Pre-commit Hook อย่างมืออาชีพ
ในโลกของการพัฒนาซอฟต์แวร์ที่มีการเปลี่ยนแปลงอยู่เสมอ การรักษาคุณภาพโค้ดให้สูงเป็นสิ่งสำคัญยิ่ง โค้ดที่สะอาด จัดรูปแบบดี และปราศจากบั๊กไม่เพียงแต่ช่วยลดต้นทุนในการบำรุงรักษา แต่ยังส่งเสริมการทำงานร่วมกันและเร่งรอบการพัฒนาให้เร็วขึ้นอีกด้วย เทคนิคหนึ่งที่ทรงพลังในการบังคับใช้คุณภาพโค้ดคือการใช้ ประตูคุณภาพโค้ด (code quality gates) ผ่าน pre-commit hooks บทความนี้จะให้คำแนะนำที่ครอบคลุมเกี่ยวกับการตั้งค่า pre-commit hooks สำหรับโปรเจกต์ JavaScript เพื่อให้คุณสามารถตรวจสอบคุณภาพโค้ดได้โดยอัตโนมัติก่อนที่โค้ดจะถูกส่งไปยัง repository ของคุณ
Pre-commit Hooks คืออะไร?
Git hooks คือสคริปต์ที่ Git จะรันก่อนหรือหลังเหตุการณ์ต่างๆ เช่น commit, push และ receive โดยเฉพาะ pre-commit hooks จะทำงานก่อนที่การ commit จะเสร็จสิ้นสมบูรณ์ ซึ่งเป็นโอกาสสำคัญในการตรวจสอบการเปลี่ยนแปลงที่กำลังจะถูก commit และป้องกันการ commit ที่ไม่ผ่านมาตรฐานคุณภาพที่กำหนดไว้ ลองนึกภาพว่าเป็นเหมือนผู้เฝ้าประตูที่ป้องกันไม่ให้โค้ดคุณภาพต่ำเข้าสู่ codebase ของคุณ
ทำไมต้องใช้ Pre-commit Hooks เพื่อคุณภาพโค้ด JavaScript?
- ตรวจจับข้อผิดพลาดตั้งแต่เนิ่นๆ: Pre-commit hooks ช่วยตรวจจับปัญหาคุณภาพโค้ดได้ตั้งแต่ช่วงแรกๆ ของกระบวนการพัฒนา ป้องกันไม่ให้ปัญหาลุกลามต่อไป ซึ่งมีประสิทธิภาพมากกว่าการค้นพบปัญหาในระหว่างการทำ code review หรือที่แย่กว่านั้นคือในเวอร์ชัน production
- การจัดรูปแบบโค้ดอัตโนมัติ: ทำให้มั่นใจได้ว่าสไตล์ของโค้ดจะสอดคล้องกันทั่วทั้งทีมและโปรเจกต์ การจัดรูปแบบอัตโนมัติช่วยป้องกันการถกเถียงเรื่องสไตล์และช่วยให้ codebase อ่านง่ายขึ้น
- ลดภาระการทำ Code Review: ด้วยการบังคับใช้มาตรฐานการเขียนโค้ดโดยอัตโนมัติ pre-commit hooks จะช่วยลดภาระของผู้ทำ code review ทำให้พวกเขาสามารถมุ่งเน้นไปที่การตัดสินใจเชิงสถาปัตยกรรมและโลจิกที่ซับซ้อนได้
- ปรับปรุงความสามารถในการบำรุงรักษาโค้ด: codebase ที่มีความสอดคล้องและมีคุณภาพสูงจะง่ายต่อการบำรุงรักษาและพัฒนาต่อยอดในอนาคต
- บังคับใช้ความสอดคล้องกัน: ช่วยให้มั่นใจได้ว่าโค้ดทั้งหมดเป็นไปตามมาตรฐานของโปรเจกต์ ไม่ว่านักพัฒนาคนไหนจะเป็นคนเขียน สิ่งนี้สำคัญอย่างยิ่งในทีมที่ทำงานแบบกระจายตัวจากสถานที่ต่างๆ – เช่น ลอนดอน โตเกียว และบัวโนสไอเรส – ซึ่งสไตล์การเขียนโค้ดของแต่ละคนอาจแตกต่างกัน
เครื่องมือสำคัญสำหรับคุณภาพโค้ด JavaScript
มีเครื่องมือหลายอย่างที่นิยมใช้ร่วมกับ pre-commit hooks เพื่อทำให้การตรวจสอบคุณภาพโค้ด JavaScript เป็นไปโดยอัตโนมัติ:
- ESLint: linter สำหรับ JavaScript ที่ทรงพลังซึ่งช่วยระบุข้อผิดพลาดที่อาจเกิดขึ้น บังคับใช้สไตล์การเขียนโค้ด และช่วยปรับปรุงความสามารถในการอ่านโค้ด รองรับกฎที่หลากหลายและสามารถกำหนดค่าได้อย่างยืดหยุ่น
- Prettier: code formatter ที่มีความเห็นเป็นของตัวเอง (opinionated) ซึ่งจะจัดรูปแบบโค้ดโดยอัตโนมัติเพื่อให้เป็นไปตามสไตล์ที่สอดคล้องกัน รองรับ JavaScript, TypeScript, JSX และภาษาอื่นๆ อีกมากมาย
- Husky: เครื่องมือที่ช่วยให้การจัดการ Git hooks เป็นเรื่องง่าย ช่วยให้คุณสามารถกำหนดสคริปต์ที่จะทำงานในขั้นตอนต่างๆ ของ Git workflow ได้
- lint-staged: เครื่องมือที่รัน linter และ formatter เฉพาะกับไฟล์ที่ถูก staged เท่านั้น ซึ่งช่วยเพิ่มความเร็วในกระบวนการ pre-commit ได้อย่างมาก เป็นการป้องกันการตรวจสอบไฟล์ที่ไม่จำเป็นซึ่งไม่มีการเปลี่ยนแปลง
การตั้งค่า Pre-commit Hooks: คำแนะนำทีละขั้นตอน
นี่คือคำแนะนำโดยละเอียดเกี่ยวกับวิธีการตั้งค่า pre-commit hooks สำหรับโปรเจกต์ JavaScript ของคุณโดยใช้ Husky และ lint-staged:
ขั้นตอนที่ 1: ติดตั้ง Dependencies
ขั้นแรก ติดตั้ง package ที่จำเป็นในรูปแบบ development dependencies โดยใช้ npm หรือ yarn:
npm install --save-dev husky lint-staged eslint prettier
หรือใช้ yarn:
yarn add --dev husky lint-staged eslint prettier
ขั้นตอนที่ 2: เริ่มต้นการใช้งาน Husky
Husky ช่วยให้กระบวนการจัดการ Git hooks ง่ายขึ้น เริ่มต้นการใช้งานด้วยคำสั่งต่อไปนี้:
npx husky install
คำสั่งนี้จะสร้างไดเรกทอรี `.husky` ในโปรเจกต์ของคุณ ซึ่งจะใช้เก็บ Git hooks ต่างๆ
ขั้นตอนที่ 3: กำหนดค่า Pre-commit Hook
เพิ่ม pre-commit hook โดยใช้ Husky:
npx husky add .husky/pre-commit "npx lint-staged"
คำสั่งนี้จะสร้างไฟล์ `pre-commit` ในไดเรกทอรี `.husky` และเพิ่มคำสั่ง `npx lint-staged` เข้าไป ซึ่งเป็นการบอก Git ให้รัน lint-staged ก่อนการ commit ทุกครั้ง
ขั้นตอนที่ 4: กำหนดค่า lint-staged
lint-staged ช่วยให้คุณสามารถรัน linter และ formatter เฉพาะกับไฟล์ที่ถูก staged ซึ่งช่วยเพิ่มความเร็วในกระบวนการ pre-commit ได้อย่างมาก สร้างไฟล์ `lint-staged.config.js` (หรือ `lint-staged.config.mjs` สำหรับ ES modules) ที่ root ของโปรเจกต์และกำหนดค่าดังนี้:
module.exports = {
'*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'],
};
การตั้งค่านี้บอกให้ lint-staged รัน ESLint และ Prettier กับไฟล์ JavaScript และ TypeScript ทั้งหมดที่ถูก staged โดยแฟล็ก `--fix` ใน ESLint จะแก้ไขข้อผิดพลาด linting ที่สามารถแก้ไขได้โดยอัตโนมัติ และแฟล็ก `--write` ใน Prettier จะจัดรูปแบบไฟล์และเขียนทับด้วยโค้ดที่จัดรูปแบบแล้ว
อีกทางเลือกหนึ่ง คุณสามารถกำหนดค่าได้โดยตรงในไฟล์ `package.json` ของคุณ:
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write"
]
}
}
ขั้นตอนที่ 5: กำหนดค่า ESLint
หากคุณยังไม่ได้ทำ ให้กำหนดค่า ESLint สำหรับโปรเจกต์ของคุณ คุณสามารถสร้างไฟล์กำหนดค่า ESLint โดยใช้คำสั่งต่อไปนี้:
npx eslint --init
คำสั่งนี้จะนำคุณผ่านกระบวนการสร้างไฟล์กำหนดค่า ESLint (`.eslintrc.js`, `.eslintrc.json` หรือ `.eslintrc.yml`) ตามความต้องการของโปรเจกต์ของคุณ คุณสามารถเลือกจากการตั้งค่าที่กำหนดไว้ล่วงหน้าหลากหลายแบบหรือสร้างกฎของคุณเองก็ได้
ตัวอย่างไฟล์ `.eslintrc.js`:
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended',
'prettier'
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: 12,
sourceType: 'module'
},
plugins: [
'react',
'@typescript-eslint'
],
rules: {
'no-unused-vars': 'warn',
'react/prop-types': 'off'
}
};
การตั้งค่านี้ขยายกฎที่แนะนำของ ESLint, กฎที่แนะนำของ React, กฎที่แนะนำของ TypeScript และผสานการทำงานกับ Prettier นอกจากนี้ยังปิดการใช้งานกฎ `react/prop-types` และตั้งค่ากฎ `no-unused-vars` ให้เป็นแค่การเตือน (warning)
ขั้นตอนที่ 6: กำหนดค่า Prettier
กำหนดค่า Prettier โดยการสร้างไฟล์ `.prettierrc.js` (หรือ `.prettierrc.json`, `.prettierrc.yml`, หรือ `.prettierrc.toml`) ที่ root ของโปรเจกต์ คุณสามารถปรับแต่งตัวเลือกการจัดรูปแบบของ Prettier ให้ตรงกับแนวทางสไตล์ของโปรเจกต์ของคุณได้
ตัวอย่างไฟล์ `.prettierrc.js`:
module.exports = {
semi: false,
trailingComma: 'all',
singleQuote: true,
printWidth: 120,
tabWidth: 2
};
การตั้งค่านี้กำหนดให้ Prettier ใช้ single quotes, ไม่ใช้ semicolons, มี trailing commas, กำหนดความกว้างของบรรทัดที่ 120 ตัวอักษร และความกว้างของแท็บที่ 2 ช่องว่าง
อีกทางเลือกหนึ่ง คุณสามารถกำหนดค่า Prettier ภายใน `package.json` ได้:
{
"prettier": {
"semi": false,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 120,
"tabWidth": 2
}
}
ขั้นตอนที่ 7: ทดสอบการตั้งค่าของคุณ
ในการทดสอบการตั้งค่าของคุณ ให้ stage การเปลี่ยนแปลงบางอย่างและลอง commit ดู ตัวอย่างเช่น:
git add .
git commit -m "Test pre-commit hook"
หากมีปัญหาด้าน linting หรือการจัดรูปแบบ ESLint และ Prettier จะแก้ไขให้โดยอัตโนมัติ (หากทำได้) หรือรายงานข้อผิดพลาด หากมีข้อผิดพลาดถูกรายงาน การ commit จะถูกยกเลิก เพื่อให้คุณสามารถแก้ไขปัญหาก่อนที่จะ commit อีกครั้ง
ตัวเลือกการตั้งค่าขั้นสูง
การใช้ Linters และ Formatters อื่นๆ
คุณสามารถผสานการทำงานของ linter และ formatter อื่นๆ เข้ากับการตั้งค่า pre-commit hook ของคุณได้อย่างง่ายดาย ตัวอย่างเช่น คุณสามารถใช้ Stylelint สำหรับการ linting ไฟล์ CSS หรือ SASS:
npm install --save-dev stylelint stylelint-config-standard
จากนั้น อัปเดตไฟล์ `lint-staged.config.js` ของคุณเพื่อรวม Stylelint เข้าไปด้วย:
module.exports = {
'*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'],
'*.{css,scss}': ['stylelint --fix'],
};
การรันเทสต์ก่อน Commit
คุณยังสามารถรัน unit tests ของคุณเป็นส่วนหนึ่งของ pre-commit hook ได้ ซึ่งจะช่วยให้มั่นใจได้ว่าโค้ดของคุณทำงานได้อย่างถูกต้องก่อนที่จะถูก commit สมมติว่าคุณใช้ Jest:
npm install --save-dev jest
อัปเดตไฟล์ `lint-staged.config.js` ของคุณเพื่อรวมคำสั่ง test เข้าไป:
module.exports = {
'*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write', 'jest --findRelatedTests'],
'*.{css,scss}': ['stylelint --fix'],
};
แฟล็ก `--findRelatedTests` จะบอกให้ Jest รันเฉพาะ test ที่เกี่ยวข้องกับไฟล์ที่เปลี่ยนแปลง ซึ่งช่วยเพิ่มความเร็วในกระบวนการได้อย่างมาก
การข้าม Pre-commit Hooks
ในบางกรณี คุณอาจต้องการข้าม pre-commit hooks ชั่วคราว คุณสามารถทำได้โดยใช้แฟล็ก `--no-verify` กับคำสั่ง `git commit`:
git commit --no-verify -m "Commit message"
อย่างไรก็ตาม โดยทั่วไปแนะนำให้หลีกเลี่ยงการข้าม hook เว้นแต่จะจำเป็นจริงๆ เนื่องจากมันมีบทบาทสำคัญในการรักษาคุณภาพของโค้ด
การแก้ไขปัญหาที่พบบ่อย
- Hooks ไม่ทำงาน: ตรวจสอบให้แน่ใจว่า Husky ได้รับการติดตั้งและเริ่มต้นอย่างถูกต้อง และมีไดเรกทอรี `.husky` อยู่ที่ root ของโปรเจกต์ของคุณ และตรวจสอบว่าไฟล์ `pre-commit` ในไดเรกทอรี `.husky` มีสิทธิ์ในการรัน (executable)
- ข้อผิดพลาดจากการ linting ไม่ถูกแก้ไข: ตรวจสอบให้แน่ใจว่ามีการใช้แฟล็ก `--fix` กับ ESLint และการตั้งค่า ESLint ของคุณถูกกำหนดให้แก้ไขข้อผิดพลาดบางประเภทโดยอัตโนมัติ
- Prettier ไม่จัดรูปแบบไฟล์: ตรวจสอบให้แน่ใจว่ามีการใช้แฟล็ก `--write` กับ Prettier และการตั้งค่า Prettier ของคุณถูกกำหนดไว้อย่างถูกต้อง
- Pre-commit hooks ทำงานช้า: ใช้ lint-staged เพื่อรัน linter และ formatter เฉพาะกับไฟล์ที่ถูก staged เท่านั้น และพิจารณาปรับปรุงการตั้งค่า ESLint และ Prettier ของคุณเพื่อลดจำนวนกฎและการตั้งค่าที่ต้องตรวจสอบ
- การตั้งค่าขัดแย้งกัน: ตรวจสอบให้แน่ใจว่าการตั้งค่า ESLint และ Prettier ของคุณไม่ขัดแย้งกัน หากขัดแย้งกัน คุณอาจต้องปรับการตั้งค่าอย่างใดอย่างหนึ่งหรือทั้งสองอย่างเพื่อแก้ไขข้อขัดแย้ง ลองพิจารณาใช้การตั้งค่าร่วมกันเช่น `eslint-config-prettier` และ `eslint-plugin-prettier` เพื่อหลีกเลี่ยงข้อขัดแย้ง
แนวทางปฏิบัติที่ดีที่สุดสำหรับ Pre-commit Hooks
- ทำให้ hooks ทำงานเร็ว: hooks ที่ทำงานช้าอาจส่งผลกระทบอย่างมากต่อประสิทธิภาพการทำงานของนักพัฒนา ใช้ lint-staged เพื่อประมวลผลเฉพาะไฟล์ที่ถูก staged และปรับปรุงการตั้งค่า linter และ formatter ของคุณ
- แสดงข้อความข้อผิดพลาดที่ชัดเจน: เมื่อ hook ทำงานไม่สำเร็จ ให้แสดงข้อความข้อผิดพลาดที่ชัดเจนและให้ข้อมูลเพื่อเป็นแนวทางให้นักพัฒนาแก้ไขปัญหาได้
- ทำให้เป็นอัตโนมัติให้มากที่สุด: ทำให้การจัดรูปแบบโค้ดและการ linting เป็นแบบอัตโนมัติเพื่อลดการทำงานด้วยตนเองและรับประกันความสอดคล้องกัน
- ให้ความรู้กับทีมของคุณ: ตรวจสอบให้แน่ใจว่าสมาชิกในทีมทุกคนเข้าใจวัตถุประสงค์ของ pre-commit hooks และวิธีการใช้งานอย่างมีประสิทธิภาพ
- ใช้การตั้งค่าที่สอดคล้องกัน: รักษาการตั้งค่าที่สอดคล้องกันสำหรับ ESLint, Prettier และเครื่องมืออื่นๆ ทั่วทั้งโปรเจกต์ สิ่งนี้จะช่วยให้มั่นใจได้ว่าโค้ดทั้งหมดจะถูกจัดรูปแบบและ linting ในลักษณะเดียวกัน พิจารณาใช้ package การตั้งค่าร่วมที่สามารถติดตั้งและอัปเดตได้ง่ายในหลายโปรเจกต์
- ทดสอบ hooks ของคุณ: ทดสอบ pre-commit hooks ของคุณอย่างสม่ำเสมอเพื่อให้แน่ใจว่ามันทำงานได้อย่างถูกต้องและไม่ก่อให้เกิดปัญหาที่ไม่คาดคิด
ข้อควรพิจารณาในระดับโลก
เมื่อทำงานในทีมที่กระจายตัวอยู่ทั่วโลก ควรพิจารณาสิ่งต่อไปนี้:
- เวอร์ชันของเครื่องมือที่สอดคล้องกัน: ตรวจสอบให้แน่ใจว่าสมาชิกในทีมทุกคนใช้ ESLint, Prettier, Husky และ lint-staged เวอร์ชันเดียวกัน ซึ่งสามารถทำได้โดยการระบุเวอร์ชันในไฟล์ `package.json` ของคุณและใช้ package manager เช่น npm หรือ yarn เพื่อติดตั้ง dependencies
- ความเข้ากันได้ข้ามแพลตฟอร์ม: ทดสอบ pre-commit hooks ของคุณบนระบบปฏิบัติการต่างๆ (Windows, macOS, Linux) เพื่อให้แน่ใจว่าทำงานได้อย่างถูกต้องบนทุกแพลตฟอร์ม ใช้เครื่องมือและคำสั่งที่ทำงานข้ามแพลตฟอร์มได้เมื่อเป็นไปได้
- ความแตกต่างของเขตเวลา: คำนึงถึงความแตกต่างของเขตเวลาเมื่อสื่อสารกับสมาชิกในทีมเกี่ยวกับปัญหา pre-commit hook ให้คำแนะนำและตัวอย่างที่ชัดเจนเพื่อช่วยให้พวกเขาแก้ไขปัญหาได้อย่างรวดเร็ว
- การรองรับภาษา: หากโปรเจกต์ของคุณเกี่ยวข้องกับการทำงานกับหลายภาษา ตรวจสอบให้แน่ใจว่า pre-commit hooks ของคุณรองรับทุกภาษาที่ใช้ในโปรเจกต์ คุณอาจต้องติดตั้ง linter และ formatter เพิ่มเติมสำหรับแต่ละภาษา
สรุป
การใช้ pre-commit hooks เป็นวิธีที่มีประสิทธิภาพในการบังคับใช้คุณภาพโค้ด ปรับปรุงการทำงานร่วมกันในทีม และลดต้นทุนการบำรุงรักษาในโปรเจกต์ JavaScript ด้วยการผสานรวมเครื่องมืออย่าง ESLint, Prettier, Husky และ lint-staged คุณสามารถทำให้การจัดรูปแบบโค้ด, การ linting และการทดสอบเป็นไปโดยอัตโนมัติ ทำให้มั่นใจได้ว่ามีเพียงโค้ดคุณภาพสูงเท่านั้นที่จะถูก commit เข้าสู่ repository ของคุณ ด้วยการทำตามขั้นตอนที่ระบุไว้ในคู่มือนี้ คุณสามารถตั้งค่าประตูคุณภาพโค้ดที่แข็งแกร่งซึ่งจะช่วยให้คุณสร้างแอปพลิเคชัน JavaScript ที่สะอาดขึ้น ดูแลรักษาง่ายขึ้น และเชื่อถือได้มากขึ้น นำแนวทางปฏิบัตินี้ไปใช้และยกระดับเวิร์กโฟลว์การพัฒนาของทีมคุณตั้งแต่วันนี้